{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Speeding up Numpy and Pandas using `numexpr` and `pd.eval`\n",
    "## Dr. Tirthajyoti Sarkar, Fremont, CA"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import numexpr as ne\n",
    "import pandas as pd\n",
    "import matplotlib.pyplot as plt"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## A simple vector-scalar addition"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "a = np.arange(1e6)\n",
    "b = np.arange(1e6)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "3.55 ms ± 52.1 µs per loop (mean ± std. dev. of 10 runs, 200 loops each)\n"
     ]
    }
   ],
   "source": [
    "%%timeit -n200 -r10\n",
    "c = a+1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1.94 ms ± 86.5 µs per loop (mean ± std. dev. of 10 runs, 200 loops each)\n"
     ]
    }
   ],
   "source": [
    "%%timeit -n200 -r10\n",
    "c = ne.evaluate(\"a + 1\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Arithmatic operation involving two arrays"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "11.7 ms ± 177 µs per loop (mean ± std. dev. of 10 runs, 100 loops each)\n"
     ]
    }
   ],
   "source": [
    "%%timeit -n100 -r10\n",
    "c = 2*a+3*b"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2.14 ms ± 130 µs per loop (mean ± std. dev. of 10 runs, 100 loops each)\n"
     ]
    }
   ],
   "source": [
    "%%timeit -n100 -r10\n",
    "c = ne.evaluate(\"2*a+3*b\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## More complicated operation involving more arrays\n",
    "\n",
    "Evaluate,\n",
    "\n",
    "$$c = \\frac{a_1^2+2a_2+(3/a_3)}{\\sqrt{a_4^2+a_5^2}}$$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 56,
   "metadata": {},
   "outputs": [],
   "source": [
    "a = np.random.normal(size=(1000000,5))\n",
    "a1,a2,a3,a4,a5 = a[:,0],a[:,1],a[:,2],a[:,3],a[:,4]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 59,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "47 ms ± 220 µs per loop (mean ± std. dev. of 10 runs, 100 loops each)\n"
     ]
    }
   ],
   "source": [
    "%%timeit -n100 -r10\n",
    "c = (a1**2+2*a2+(3/a3))/(np.sqrt(a4**2+a5**2))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 60,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "3.96 ms ± 218 µs per loop (mean ± std. dev. of 10 runs, 100 loops each)\n"
     ]
    }
   ],
   "source": [
    "%%timeit -n100 -r10\n",
    "ne.evaluate(\"(a1**2+2*a2+(3/a3))/(sqrt(a4**2+a5**2))\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Expression involving a conditional (boolean filtering)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 61,
   "metadata": {},
   "outputs": [],
   "source": [
    "x1 = np.random.random(1000000)\n",
    "x2 = np.random.random(1000000)\n",
    "y1 = np.random.random(1000000)\n",
    "y2 = np.random.random(1000000)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 62,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "23.2 ms ± 143 µs per loop (mean ± std. dev. of 10 runs, 100 loops each)\n"
     ]
    }
   ],
   "source": [
    "%%timeit -n100 -r10\n",
    "c = np.sqrt((x1-x2)**2+(y1-y2)**2) > 0.5"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 63,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1.86 ms ± 112 µs per loop (mean ± std. dev. of 10 runs, 100 loops each)\n"
     ]
    }
   ],
   "source": [
    "%%timeit -n100 -r10\n",
    "c = ne.evaluate(\"sqrt((x1-x2)**2+(y1-y2)**2) > 0.5\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "763 µs ± 85.4 µs per loop (mean ± std. dev. of 10 runs, 100 loops each)\n"
     ]
    }
   ],
   "source": [
    "%%timeit -n100 -r10\n",
    "c = ne.evaluate(\"2*a+3*b > 3.5\",optimization='moderate')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Expression involving complex numbers"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 64,
   "metadata": {},
   "outputs": [],
   "source": [
    "a = np.random.random(1000000)\n",
    "b = np.random.random(1000000)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 65,
   "metadata": {},
   "outputs": [],
   "source": [
    "cplx = a + b*1j"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 66,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "55.9 ms ± 159 µs per loop (mean ± std. dev. of 10 runs, 100 loops each)\n"
     ]
    }
   ],
   "source": [
    "%%timeit -n100 -r10\n",
    "c = np.log10(cplx)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 67,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "9.9 ms ± 117 µs per loop (mean ± std. dev. of 10 runs, 100 loops each)\n"
     ]
    }
   ],
   "source": [
    "%%timeit -n100 -r10\n",
    "c = ne.evaluate(\"log10(cplx)\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## How the array size impacts the speed improvement"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [],
   "source": [
    "from time import time"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [],
   "source": [
    "result_np = {'Size':[],'Time':[]}\n",
    "for i in [int(10**(j/5)) for j in range(25,40)]:\n",
    "    a = np.random.random(size=i)\n",
    "    b = np.random.random(size=i)\n",
    "    times = [0]*10\n",
    "    for j in range(10):\n",
    "        t1 = time()\n",
    "        c = (2*a+3*b > 3.5)\n",
    "        t2 = time()\n",
    "        times[j]=(t2-t1)*1000\n",
    "    times = np.array(times)\n",
    "    result_np['Size'].append(i)\n",
    "    result_np['Time'].append(times.mean())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [],
   "source": [
    "result_ne = {'Size':[],'Time':[]}\n",
    "for i in [int(10**(j/5)) for j in range(25,40)]:\n",
    "    a = np.random.random(size=i)\n",
    "    b = np.random.random(size=i)\n",
    "    times = [0]*10\n",
    "    for j in range(10):\n",
    "        t1 = time()\n",
    "        c = ne.evaluate(\"2*a+3*b > 3.5\")\n",
    "        t2 = time()\n",
    "        times[j]=(t2-t1)*1000\n",
    "    times = np.array(times)\n",
    "    result_ne['Size'].append(i)\n",
    "    result_ne['Time'].append(times.mean()) "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [],
   "source": [
    "def speed_benchmark(result1,result2,leg_text):\n",
    "    \"\"\"\n",
    "    Plots timing results\n",
    "    \"\"\"\n",
    "    plt.semilogx(result1['Size'],result1['Time'],c='blue',marker='o')\n",
    "    plt.semilogx(result2['Size'],result2['Time'],c='k',marker='^')\n",
    "    plt.grid(True)\n",
    "    plt.legend(leg_text,fontsize=14)\n",
    "    plt.xticks(fontsize=13)\n",
    "    plt.yticks(fontsize=13)\n",
    "    plt.xlabel('Number of elements in the array',fontsize=15)\n",
    "    plt.ylabel(\"Time (milliseconds)\",fontsize=15)\n",
    "    plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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06FDB1JSApuWDjZt2jSeeeYZ1q9fX6N6HXPMMUyePJkjjjiCiRMn0rZtWxISErjhhhvo0aMHd955J6rKsmXLgm6fn5/P3/72N7Kzsxk6dCgAl19+OU8//XTpOu+//z47duzg0ktr3KfUmKhWUgJvvw1nngkJCbW3HxuepBz+ZwB79+ZVeudOt27uUlWgrl0hWu4+nDhxIldffTXPPPMMQ4cO5fzzz+fII4+sdnkDBw7kt7/9LbfffjsLFiyodjn+l5JEhPbt29OrV6/StISEBFq1anVQj+3LLruMMWPGkJeXR0pKCg888ADDhrkb90aOHMndd9/NsmXLOPnkk5k7dy7nnnsubdq0qXY9jYkFq1bB9u2uvaM22ai6YXLPPdCsWdm0Zs1cel2Ii4ujbPcXDurhPHnyZDZs2MC5557LsmXLOO6445g7d26N9nv//ffz9ttv89FHH1WrTuCCgz8RCZpWUlJSJm369Ol8+umnZGVl8fPPP3PzzTeX5rVt25azzz6buXPnsmvXLhYsWMBVV10V8vszJta89Za7aWfYsMrXrQkLHmEyahTMmuXONETc46xZ4b01riLt2rUjKyurTNqnvkYbP0cccQTXX389b7/9NldddRVz5swBoHHjxoDrXBeKY489ltGjR5e2LVRWp3XrwndjXIcOHejRowft27cPmn/NNdfw8ssv8+STT5Kamsppp50Wtn0bE63efBNOOQW8K9G1xoJHGI0a5e6lro17qiszZMgQ1q5dy9y5c/n222+ZNm0aH3/8cWl+Xl4e1157Lenp6WzatImVK1eydOlSjj7adRbq2rUrIsLbb7/NTz/9RE5OTpX3fffdd/Ppp5+ycuXKg+r07rvvsmDBAr766ismTpzIli1bwvOGq+D000+nTZs2TJkyhSuuuIK4OPtzN/Xb5s2wbl3tX7ICCx4xraSkhEaNXLPVb3/7W+666y4mTZpEv3792LRpExMmTChdNz4+nl9++YXLL7+cnj17ljaWP/TQQwB06tSJKVOmMGnSJFJTU0Pq7HfooYdy/fXXs3///jLpV155Zelyyimn0KJFC84777xySgk/EeGKK66gsLCQK664os72a0ykvPWWe6yL4CGB16Trq7S0NF29enXQvC+++IKjjjqq3G2jYaiLYM444wwOP/xwZs6cGemqRB3fMRs/fjzffvstixYtqvM6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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "speed_benchmark(result_np,result_ne,leg_text=['Just NumPy','With numexpr'])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Pandas `pd.eval`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "metadata": {},
   "outputs": [],
   "source": [
    "nrows, ncols = 50000, 100"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "metadata": {},
   "outputs": [],
   "source": [
    "df1, df2, df3, df4 = [pd.DataFrame(np.random.randn(nrows, ncols)) for _ in range(4)]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "55.8 ms ± 1.8 ms per loop (mean ± std. dev. of 10 runs, 20 loops each)\n"
     ]
    }
   ],
   "source": [
    "%%timeit -n20 -r10\n",
    "c=2*df1 - (df2/2) + (df3/df4)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 51,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "17.3 ms ± 539 µs per loop (mean ± std. dev. of 10 runs, 20 loops each)\n"
     ]
    }
   ],
   "source": [
    "%%timeit -n20 -r10\n",
    "pd.eval('2*df1 - (df2/2) + (df3/df4)')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## How the DataFrame size impacts the speed"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "metadata": {},
   "outputs": [],
   "source": [
    "ncols=100\n",
    "result_no_eval = {'Size':[],'Time':[]}\n",
    "for i in [int(10**(j/5)) for j in range(15,32)]:\n",
    "    df1, df2, df3, df4 = [pd.DataFrame(np.random.randn(i, ncols)) for _ in range(4)]\n",
    "    times = [0]*10\n",
    "    for j in range(10):\n",
    "        t1 = time()\n",
    "        c = df1+df2+df3+df4\n",
    "        t2 = time()\n",
    "        times[j]=(t2-t1)*1000\n",
    "    times = np.array(times)\n",
    "    result_no_eval['Size'].append(i)\n",
    "    result_no_eval['Time'].append(times.mean())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "metadata": {},
   "outputs": [],
   "source": [
    "ncols=100\n",
    "result_eval = {'Size':[],'Time':[]}\n",
    "for i in [int(10**(j/5)) for j in range(15,32)]:\n",
    "    df1, df2, df3, df4 = [pd.DataFrame(np.random.randn(i, ncols)) for _ in range(4)]\n",
    "    times = [0]*10\n",
    "    for j in range(10):\n",
    "        t1 = time()\n",
    "        c = ne.evaluate(\"df1+df2+df3+df4\")\n",
    "        t2 = time()\n",
    "        times[j]=(t2-t1)*1000\n",
    "    times = np.array(times)\n",
    "    result_eval['Size'].append(i)\n",
    "    result_eval['Time'].append(times.mean())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {},
   "outputs": [],
   "source": [
    "def speed_benchmark_pd(result1,result2,leg_text):\n",
    "    \"\"\"\n",
    "    Plots timing results\n",
    "    \"\"\"\n",
    "    plt.semilogx(result1['Size'],result1['Time'],c='blue',marker='o')\n",
    "    plt.semilogx(result2['Size'],result2['Time'],c='k',marker='^')\n",
    "    plt.grid(True)\n",
    "    plt.legend(leg_text,fontsize=14)\n",
    "    plt.xticks(fontsize=13)\n",
    "    plt.yticks(fontsize=13)\n",
    "    plt.xlabel('Number of rows in the DataFrame',fontsize=15)\n",
    "    plt.ylabel(\"Time (milliseconds)\",fontsize=15)\n",
    "    plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "speed_benchmark_pd(result_no_eval,result_eval,\n",
    "                   leg_text=['Normal boring Pandas','With pd.eval'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
